package com.buddy.qreport.template.config;

import com.buddy.qreport.template.IReportTemplate;
import com.buddy.qreport.template.annotation.ReportTemplate;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 模板类扫描器
 */
public class TemplateScanner extends ClassPathBeanDefinitionScanner {
    public TemplateScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }

    @Override
    protected void registerDefaultFilters() {

        //注册类型扫描
        super.registerDefaultFilters();
        this.addIncludeFilter(new AnnotationTypeFilter(ReportTemplate.class));
    }


    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return super.isCandidateComponent(beanDefinition)

                && beanDefinition.getMetadata().hasAnnotation(ReportTemplate.class.getName());
    }


    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> superScanResult = super.doScan(basePackages);

        Map<String, IReportTemplate> nameValueMap = new HashMap<>();

        Map<String, List<IReportTemplate>> typeValueMap = new HashMap<>();

        for (BeanDefinitionHolder holder : superScanResult) {

            try {

                Class tmpClass = Class.forName(holder.getBeanDefinition().getBeanClassName());

                if( ! IReportTemplate.class.isAssignableFrom(tmpClass)){

                    continue;
                }

                Class<IReportTemplate> reportTemplateClass = (Class<IReportTemplate>) Class.forName(holder.getBeanDefinition().getBeanClassName());

                IReportTemplate template = reportTemplateClass.newInstance();

                nameValueMap.put(template.getName(), template);


                //获取注解上type值
                ReportTemplate anno = reportTemplateClass.getAnnotation(ReportTemplate.class);

                List<IReportTemplate> iReportTemplates = typeValueMap.get(anno.type());

                if (iReportTemplates == null) {

                    iReportTemplates = new ArrayList<>();

                    typeValueMap.put(anno.type(), iReportTemplates);

                }

                iReportTemplates.add(template);


            } catch (Exception e) {
                e.printStackTrace();
            }


        }

        //将分类好的集合注入到TemplateManager

        TemplateManager manager = TemplateManager.getInstance();

        try {


            Field templateNameValueMapField = TemplateManager.class.getDeclaredField("templateNameValueMap");
            templateNameValueMapField.setAccessible(true);
            templateNameValueMapField.set(manager,nameValueMap);


            Field templateTypeValueMapField = TemplateManager.class.getDeclaredField("templateTypeValueMap");
            templateTypeValueMapField.setAccessible(true);
            templateTypeValueMapField.set(manager,typeValueMap);


        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }


        return superScanResult;
    }
}
